﻿using System;
using System.IO;
using System.Text;
using System.Collections.Generic;

namespace Bamboo.Utils
{
    public class SimpleIni
    {
        private string _filename;
        private Encoding _encoding;
        private Dictionary<string, string> _dict = new Dictionary<string, string>();
        private StringBuilder _tempBuffer = new StringBuilder(1024);

        /// <summary>
        /// 加密密钥，如果要保存或读取密文则需要设置该属性
        /// </summary>
        public string EncryptKey { get; set; }

        public SimpleIni(string fileName, Encoding encoding)
        {
            this._filename = fileName;
            this._encoding = encoding;
        }

        public void Load()
        {
            _dict.Clear();
            if (!File.Exists(_filename)) return;
            var lines = File.ReadAllLines(_filename, _encoding);
            foreach (var line in lines)
            {
                int index = line.IndexOf('=');
                if (index <= 0) continue;
                string key = line.Substring(0, index);
                string value = line.Substring(index + 1, line.Length - index - 1);
                _dict[key] = value;
            }
        }

        public void Save()
        {
            var s = new StringBuilder(128 * 1024);
            foreach (var item in _dict)
            {
                s.AppendLine(item.Key + "=" + item.Value);
            }
            var fullname = Path.GetFullPath(_filename);
            var dirname = Path.GetDirectoryName(fullname);
            if (!Directory.Exists(dirname))
            {
                Directory.CreateDirectory(dirname);
            }
            File.WriteAllText(fullname, s.ToString(), _encoding);
        }

        public virtual string ReadString(string key, string defaultValue)
        {
            string v;
            if (_dict.TryGetValue(key, out v))
            {
                v = Encrypt.DES3Decrypt(v, EncryptKey);
                v = SingleLineToMultiLine(v);
                return v;
            }
            else
            {
                return defaultValue;
            }
        }

        public virtual void WriteString(string key, string value)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new Exception("key不允许为空");
            var s = MultiLineToSingleLine(value);
            _dict[key] = s;
        }

        public virtual void WriteStringEnc(string key, string value)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new Exception("key不允许为空");
            string s = MultiLineToSingleLine(value);
            s = Encrypt.DES3Encrypt(value, EncryptKey);
            _dict[key] = s;
        }

        public virtual void DeleteKey(string key)
        {
            _dict.Remove(key);
        }

        public int ReadInt(string key, int defaultValue = 0)
        {
            int value;
            if (int.TryParse(ReadString(key, ""), out value))
                return value;
            else
                return defaultValue;
        }

        public void WriteInt(string key, int value)
        {
            WriteString(key, value.ToString());
        }

        public bool ReadBool(string key, bool defaultValue = false)
        {
            bool value;
            if (bool.TryParse(ReadString(key, ""), out value))
                return value;
            else
                return defaultValue;
        }

        public void WriteBool(string key, bool value)
        {
            WriteString(key, value.ToString());
        }

        public double ReadDouble(string key, double defaultValue = 0.0)
        {
            double value;
            if (double.TryParse(ReadString(key, ""), out value))
                return value;
            else
                return defaultValue;
        }

        public void WriteDouble(string key, double value)
        {
            WriteString(key, value.ToString());
        }



        public string MultiLineToSingleLine(string input)
        {
            _tempBuffer.Clear();
            for (int i = 0; i < input.Length; ++i)
            {
                char ch = input[i];
                switch (ch)
                {
                    case '\r': _tempBuffer.Append("#13"); break;
                    case '\n': _tempBuffer.Append("#10"); break;
                    case '#': _tempBuffer.Append("#35"); break;
                    default: _tempBuffer.Append(ch); break;
                }
            }
            return _tempBuffer.ToString();
        }

        public string SingleLineToMultiLine(string input)
        {
            _tempBuffer.Clear();
            for (int i = 0; i < input.Length; ++i)
            {
                char ch = input[i];
                if (ch == '#' && i + 2 < input.Length)
                {
                    char ch2 = input[i + 1];
                    char ch3 = input[i + 2];
                    if (ch2 == '1' && ch3 == '0') _tempBuffer.Append('\n');
                    else if (ch2 == '1' && ch3 == '3') _tempBuffer.Append('\r');
                    else if (ch2 == '3' && ch3 == '5') _tempBuffer.Append('#');
                    else _tempBuffer.Append(ch);
                }
                else
                {
                    _tempBuffer.Append(ch);
                }
            }
            return _tempBuffer.ToString();
        }
    }
}